#include "vec2.h"

// constructor : an empty vector, (0,0,0)
vec2::vec2() : 
	x(0), y(0) {}

// constructor : from three values, (x,y)
vec2::vec2(float X, float Y) : 
	x(X), y(Y) {}

// constructor : from one value, (a,a,a)
vec2::vec2(float a) : 
	x(a), y(a) {}

// constructor : from an array of float[3]
vec2::vec2(float *v) :
	x(v[0]), y(v[1]) {}

// constructor : from another vector
vec2::vec2(const vec2 &v) : 
	x(v.x), y(v.y) {}

// destructor
vec2::~vec2() {}

float vec2::total(void)
{
	// addition of all values
	return x + y;
}

vec2 vec2::negated(void)
{
	// negative vector
	return vec2(-x, -y);
}

void vec2::asArray(float *arr)
{
	// values of vector to array
	arr[0] = x;
	arr[1] = y;
}

float vec2::magnitude(void)
{
	// manitude of vector
	return sqrt(*this * *this);
}

vec2 vec2::normal(void)
{
	// unit vector
	return *this / this->magnitude();
}

vec2 vec2::direction(void)
{
	// angles between (1,1,1) and this vector on each axis
	vec2 temp = this->normal();
	temp(	(float)(acos(temp.x) * RADTODEG),
			(float)(acos(temp.y) * RADTODEG)	);
	return temp;
}

float vec2::distancebetween(vec2 v)
{
	// distance between this vector and v
	vec2 temp(x - v.x, y - v.y);
	return sqrt(temp * temp);
}

float vec2::anglebetween(vec2 v)
{
	// angle between this vector and v
	float temp = *this * v;
	temp /= magnitude() * v.magnitude();
	return acos(temp) * (float)(RADTODEG);
}

float vec2::dotproduct(vec2 v)
{
	// dot product between this vector and vector v
	vec2 temp(	x * v.x,
				y * v.y	);
	return temp.total();
}

vec2 vec2::operator+ (vec2 v)
{
	// add vector v to this vector
	vec2 temp(	x + v.x,
				y + v.y	);
	return temp;
}

void vec2::operator+= (vec2 v)
{
	// add vector v to this vector
	x += v.x;
	y += v.y;
}

vec2 vec2::operator- (vec2 v)
{
	// subtract vector v from this vector
	vec2 temp(	x - v.x,
				y - v.y	);
	return temp;
}

void vec2::operator-= (vec2 v)
{
	// subtract vector v from this vector
	x -= v.x;
	y -= v.y;
}

vec2 vec2::operator* (float f)
{
	// multiply this vector by f
	vec2 temp(	x * f,
				y * f	);
	return temp;
}

void vec2::operator*= (float f)
{
	// multiply this vector by f
	x *= f;
	y *= f;
}

vec2 vec2::operator/ (float f)
{
	// divide this vector by f

	// Check for division by zero
	// Return an empty vector
	if(f == 0)
	{
		return vec2(0.0);
	}

	vec2 temp(	x / f,
				y / f	);
	return temp;
}

void vec2::operator/= (float f)
{
	// divide this vector by f

	// Check for division by zero
	// Return an empty vector
	if(f == 0)
	{
		x = y = 0;
		return;
	}

	x /= f;
	y /= f;
}

bool vec2::operator== (vec2 v)
{
	return (x == v.x) && (y == v.y);
}

bool vec2::operator!= (vec2 v)
{
	return (x != v.x) || (y != v.y);
}

bool vec2::operator> (vec2 v)
{
	return magnitude() > v.magnitude();
}

bool vec2::operator>= (vec2 v)
{
	return magnitude() >= v.magnitude();
}

bool vec2::operator< (vec2 v)
{
	return magnitude() < v.magnitude();
}

bool vec2::operator<= (vec2 v)
{
	return magnitude() <= v.magnitude();
}

float vec2::operator* (vec2 v)
{
	// dot product between this vector and vector v
	return dotproduct(v);
}

void vec2::operator() (float X, float Y)
{
	x = X; y = Y;
}

vec2 operator- (vec2 v)
{
	return v.negated();
}

float vec2::operator[] (int a)
{
	switch(a)
	{
	case 0: return x;
	case 1: return y;
	default: return 0;
	}
}

ostream& operator<< (ostream &os, vec2 &v)
{
	// output vector contents to console in the format: x=1 y=2
	os	<< "x="  << v.x
		<< " y=" << v.y;
	return os;
}

vec2 detectzero(vec2 v)
{
	return vec2( detectzero(v.x), detectzero(v.y) );
}